package com.hk.weixin.security.miniapp;

import com.hk.core.authentication.api.UserPrincipal;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

/**
 * Wechat 认证 Token
 *
 * @author kevin
 * @date 2018年2月8日上午11:14:18
 */
public class WeiXinMiniappAuthenticationToken extends AbstractAuthenticationToken {

    /**
     * 认证对象
     */
    private transient final Object principal;

    /**
     * 微信用户，未认证
     */
    public WeiXinMiniappAuthenticationToken(Object principal) {
        super(null);
        this.principal = principal;
        setAuthenticated(false);
    }

    /**
     * 微信用户，已认证
     *
     * @param principal   认证对象
     * @param authorities 权限
     */
    public WeiXinMiniappAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true);
    }

    @Override
    public void setAuthenticated(boolean authenticated) {
        if (authenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }
        super.setAuthenticated(false);
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public String getName() {
        return (principal instanceof UserPrincipal userPrincipal) ?
                userPrincipal.getAccount() : super.getName();
    }

    @Override
    public Object getPrincipal() {
        return principal;
    }

    @Override
    public boolean equals(Object obj) {
        if (!super.equals(obj)) {
            return false;
        }
        if (obj instanceof WeiXinMiniappAuthenticationToken token) {
            return this.principal.equals(token.principal);
        }
        return false;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + this.principal.hashCode();
        return result;
    }
}
